package edu.calpoly.android.echoes;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.database.Cursor;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class DrawView extends SurfaceView implements SurfaceHolder.Callback {
	public static int NUM_SCREENS = 2;

    private List<MyDrawableShapes> points = new ArrayList<MyDrawableShapes>();
    MyCircle theMovingCircle, latinCircle;
    ColorSelectMenu csm;
    private MyDrawThread _mdThread;
    private Paint paint;
    private AudioPlayer ap;
    
    private DatabaseInterlace dbI;
    
    private static final float STANDARD_FREQUENCY = 1.0f;
    private int chordSelection = 0;

	private PauseOverlay _pauseOverlay = new PauseOverlay();
	
	private int current_screen = 0;
	private ShapeDBAdapter m_shapeDB;
	private boolean m_newGame;
    
    /**
	 * Contains the list of Jokes the Activity will present to the user.
	 **/
	protected Cursor m_arrShapeList;

    public DrawView(Context context, AudioPlayer ap, ShapeDBAdapter db, boolean newGame) {
        super(context);
        getHolder().addCallback(this);
        _mdThread = new MyDrawThread(getHolder(), this);
        this.ap = ap;
        m_newGame = newGame;
        m_shapeDB = db;
        dbI = new DatabaseInterlace(context, m_shapeDB);
        
        if(!m_newGame) {
        	ArrayList<MyDrawableShapes> myShapes = new ArrayList<MyDrawableShapes>();
        	if(myShapes != null)
        		points.addAll(dbI.loadGame());
        }
        
        m_shapeDB = db;
        
        //TODO based on chord
        chordSelection = AudioPlayer.PIANO_CHORD;
        //setFocusableInTouchMode(true);

        //this.setOnTouchListener(this);
        
        //Database initialization
        /*m_shapeDB = new ShapeDBAdapter(context);
        m_shapeDB.open();
        m_arrShapeList = m_shapeDB.getAllShapes();
        startManagingCursor(m_arrShapeList);*/
        
        csm = new ColorSelectMenu();
        paint = new Paint(Color.BLUE);
        theMovingCircle = new MyCircle(65,50,10,paint,ap);
        theMovingCircle.setScreenNumber(0);
        latinCircle = new MyCircle(65,50,10,paint,ap);
        latinCircle.setScreenNumber(1);
        setFocusable(true);
    }

    @Override
    public void onDraw(Canvas canvas) {
    	canvas.drawColor(Color.LTGRAY);
    	
    	if(current_screen == 0)
    		theMovingCircle.drawMe(canvas);
    	else
    		latinCircle.drawMe(canvas);
    	
    	synchronized (points) {
	        for (MyDrawableShapes point : points) {
	        	if(point instanceof MyRectangle) {
	        		if(point.getScreenNumber() == 0 && !Echoes.DISPLAY_PAUSE_SCREEN &&
	        				MyPhysics.checkCollision(theMovingCircle,(MyRectangle)point)) {
	        			ap.playSound((AudioPlayer.PIANO_CHORD + ((MyRectangle) point).getColorIndex()), STANDARD_FREQUENCY);
	        		}
	        		if(point.getScreenNumber() == 1 && !Echoes.DISPLAY_PAUSE_SCREEN &&
	        				MyPhysics.checkCollision(latinCircle,(MyRectangle)point)) {
	        			ap.playSound((AudioPlayer.LATIN_CHORD + ((MyRectangle) point).getColorIndex()), STANDARD_FREQUENCY);
	        		}
	        	}
	        	if(point.getScreenNumber() == current_screen) {
	        		point.drawMe(canvas);
	        	}
	        }
    	}
        
    	if(Echoes.DISPLAY_PAUSE_SCREEN) {
    		_pauseOverlay.drawMe(canvas);
    		csm.drawMenu(canvas);
    	}
    	else {
	    	theMovingCircle.updateLoc(canvas);
	    	latinCircle.updateLoc(canvas);
    	}
    }
        

    public boolean onTouchEvent(MotionEvent event) {
    	if(Echoes.DISPLAY_PAUSE_SCREEN) {
    		return pauseTouch(event);
    	} else {
    		return unpausedTouch(event);
    	}
    }
    
    public boolean pauseTouch(MotionEvent event) {
    	synchronized (_mdThread.getSurfaceHolder()) {
            if (event.getAction() == MotionEvent.ACTION_DOWN){
            	int selection = _pauseOverlay.checkCollision((int)event.getX(),(int)event.getY());
            	
            	if(selection == _pauseOverlay.PAUSE_SAVE) {
            		ArrayList shapes = new ArrayList<MyDrawableShapes>(points);
            		dbI.saveGame(shapes);
            	} else if(selection == _pauseOverlay.PAUSE_LEFT ||
            			  selection == _pauseOverlay.PAUSE_RIGHT) {
            		changeScreen(selection);
            	} else if(selection == _pauseOverlay.PAUSE_START) {
            		Echoes.DISPLAY_PAUSE_SCREEN = !Echoes.DISPLAY_PAUSE_SCREEN;
            	} else if(selection == _pauseOverlay.PAUSE_QUIT) {
            		//((Activity) context).finish();
            	}
            	
            	if (csm.isMenuPress((int)event.getX(),(int)event.getY())) {
            		csm.setMenuSelection((int)event.getX(),(int)event.getY());
            	} 
            } else {
            	
            }
            return true;
    	}
    }
    
    public boolean unpausedTouch(MotionEvent event) {
    	synchronized (_mdThread.getSurfaceHolder()) {
            if (event.getAction() == MotionEvent.ACTION_DOWN){
            	MyRectangle toInsert = new MyRectangle(event.getX()-30,event.getY()-5,event.getX()+30,event.getY()+5, paint, csm.getCurrentColor());
            	toInsert.setScreenNumber(current_screen);
            	
            	if(!spaceOccupied(toInsert)) {
            		synchronized(points){
            			points.add(toInsert);
            		}
            	}
            }
            return true;
    	}
    }
    
    private boolean spaceOccupied(MyRectangle r) {
    	if(r.getScreenNumber() == 0 && MyPhysics.checkCollision(theMovingCircle,r,0))
    		return true;
    	if(r.getScreenNumber() == 1 && MyPhysics.checkCollision(latinCircle,r,0))
    		return true;
    	
    	synchronized(points) {
	        for (MyDrawableShapes point : points) {
	        	if(point instanceof MyRectangle) {
	        		if(point.getScreenNumber() == r.getScreenNumber()) {
		        		if(MyPhysics.checkCollision(r, ((MyRectangle) point)))
		        			return true;
	        		}
	        	}
	        }
    	}
    	
    	return false;
    }
    
    public void changeScreen(int selection) {
    	if(selection == PauseOverlay.PAUSE_LEFT) {
    		if(current_screen > 0) {
    			current_screen--;
    			setChordSelection();
    		}
    	} else if(selection == PauseOverlay.PAUSE_RIGHT) {
    		if(current_screen < NUM_SCREENS - 1) {
    			current_screen++;
    			setChordSelection();
    		}
    	}
    }
    
    public void setChordSelection() {
    	if(current_screen == 0) {
    		chordSelection = AudioPlayer.PIANO_CHORD;
    	} else if(current_screen == 1) {
    		chordSelection = AudioPlayer.LATIN_CHORD;
    	}
    }
    
    public void undoLastShape() {
    	synchronized(points) {
	    	if(!points.isEmpty())
	    		points.remove(points.size());
    	}
    }

	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}

	public void surfaceCreated(SurfaceHolder holder) {
		_mdThread = new MyDrawThread(getHolder(), this);
		_mdThread.setRunning(true);
		_mdThread.start();
	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		boolean retry = true;
		_mdThread.setRunning(false);
		_mdThread = null;
		/*while (retry) {
			try {
				_mdThread.join();
				retry = false;
			} catch (InterruptedException e) {
				//try again
			}
		}*/		
	}
    
	private class MyDrawThread extends Thread {
		private SurfaceHolder _surfaceHolder;
		private DrawView _drawView;
		private boolean _run = false;
		
		public MyDrawThread (SurfaceHolder sHold, DrawView dv) {
			_surfaceHolder = sHold;
			_drawView = dv;
		}
		
		public void setRunning(boolean run) {
			_run = run;
		}
		
		public SurfaceHolder getSurfaceHolder() {
			return _surfaceHolder;
		}
		
		public void run () {
			Canvas c;
			while (_run) {
				c = null;
				try {
					c = _surfaceHolder.lockCanvas(null);
					synchronized (_surfaceHolder) {
						_drawView.onDraw(c);
					}
				} finally {
					if (c != null) {
						_surfaceHolder.unlockCanvasAndPost(c);
					}
				}
			}
			
		}
	}
    
}